home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / PRTPerVertex / main.cpp next >
Encoding:
C/C++ Source or Header  |  2004-09-28  |  74.0 KB  |  1,691 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: main.cpp
  3. //
  4. // This sample demonstrates how use D3DXSHPRTSimulation(), a per vertex  
  5. // precomputed radiance transfer (PRT) simulator that uses low-order 
  6. // spherical harmonics (SH) and records the results to a file. The sample 
  7. // then demonstrates how compress the results with clustered principal 
  8. // component analysis (CPCA) and view the compressed results with arbitrary 
  9. // lighting in real time with a vs_1_1 vertex shader
  10. //
  11. // Copyright (c) Microsoft Corporation. All rights reserved.
  12. //--------------------------------------------------------------------------------------
  13. #include "dxstdafx.h"
  14. #include <msxml.h>
  15. #include "PRTMesh.h"
  16. #include "PRTSimulator.h"
  17. #include "PRTOptionsDlg.h"
  18. #include "skybox.h"
  19. #include "resource.h"
  20.  
  21. // Enable extra D3D debugging in debug builds.  This makes D3D objects work well
  22. // in the debugger watch window, but slows down performance slightly.
  23. #if defined(DEBUG) | defined(_DEBUG)
  24. #define D3D_DEBUG_INFO
  25. #endif
  26.  
  27. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  28. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  29.  
  30.  
  31. //--------------------------------------------------------------------------------------
  32. // Global variables
  33. //--------------------------------------------------------------------------------------
  34. ID3DXFont*              g_pFont = NULL;         // Font for drawing text
  35. ID3DXSprite*            g_pTextSprite = NULL;   // Sprite for batching draw text calls
  36. CModelViewerCamera      g_Camera;               // A model viewing camera
  37. bool                    g_bShowHelp = true;     // If true, it renders the UI control text
  38. CDXUTDialog             g_HUD;                  // dialog for standard controls
  39. CDXUTDialog             g_StartUpUI;            // dialog for startup
  40. CDXUTDialog             g_StartUpUI2;           // dialog for startup
  41. CDXUTDialog             g_SimulatorRunningUI;   // dialog for while simulator running
  42. CDXUTDialog             g_RenderingUI;          // dialog for while PRT rendering 
  43. CDXUTDialog             g_RenderingUI2;         // dialog for while PRT rendering 
  44. CDXUTDialog             g_RenderingUI3;         // dialog for while PRT rendering 
  45. CDXUTDialog             g_CompressionUI;        // dialog for PRT compression settings
  46. CPRTSimulator           g_Simulator;
  47. CPRTMesh                g_PRTMesh;
  48. bool                    g_bRenderEnvMap = true;
  49. bool                    g_bRenderUI = true;
  50. bool                    g_bRenderArrows = true;
  51. bool                    g_bRenderMesh = true;
  52. bool                    g_bRenderText = true;
  53. bool                    g_bRenderWithAlbedoTexture = true;
  54. bool                    g_bRenderCompressionUI = false;
  55. float                   g_fCurObjectRadius = -1.0f;
  56. bool                    g_bWireframe = false;
  57. bool                    g_bRenderSHProjection = false;
  58. DWORD                   g_dwTechnique = 0;
  59. float                   g_fLightScaleForPRT     = 0.0f;
  60. float                   g_fLightScaleForSHIrrad = 0.0f;
  61. float                   g_fLightScaleForNdotL   = 1.0f;
  62.  
  63. #define NUM_SKY_BOXES 5
  64. CSkybox                 g_Skybox[NUM_SKY_BOXES];   
  65. float                   g_fSkyBoxLightSH[NUM_SKY_BOXES][3][D3DXSH_MAXORDER*D3DXSH_MAXORDER];  
  66. int                     g_dwSkyBoxA = (0 % NUM_SKY_BOXES);
  67. int                     g_dwSkyBoxB = (1 % NUM_SKY_BOXES);
  68.  
  69. #define MAX_LIGHTS 10
  70. CDXUTDirectionWidget    g_LightControl[MAX_LIGHTS];
  71. int                     g_nNumActiveLights;
  72. int                     g_nActiveLight;
  73.  
  74. enum APP_STATE
  75. {
  76.     APP_STATE_STARTUP,
  77.     APP_STATE_SIMULATOR_OPTIONS,
  78.     APP_STATE_SIMULATOR_RUNNING,
  79.     APP_STATE_LOAD_PRT_BUFFER,
  80.     APP_STATE_RENDER_SCENE,
  81. };
  82.  
  83. APP_STATE               g_AppState = APP_STATE_STARTUP;         // State of app
  84.  
  85.  
  86.  
  87. //--------------------------------------------------------------------------------------
  88. // UI control IDs
  89. //--------------------------------------------------------------------------------------
  90. #define IDC_STATIC              0
  91. #define IDC_TOGGLEFULLSCREEN    1
  92. #define IDC_TOGGLEREF           3
  93. #define IDC_CHANGEDEVICE        4
  94.  
  95. #define IDC_NUM_LIGHTS          6
  96. #define IDC_NUM_LIGHTS_STATIC   7
  97. #define IDC_ACTIVE_LIGHT        8
  98. #define IDC_LIGHT_SCALE         9
  99. #define IDC_LIGHT_SCALE_STATIC  10
  100.  
  101. #define IDC_LOAD_PRTBUFFER      12
  102. #define IDC_SIMULATOR           13
  103. #define IDC_STOP_SIMULATOR      14
  104.  
  105. #define IDC_ENVIRONMENT_1_SCALER 15
  106. #define IDC_ENVIRONMENT_2_SCALER 16
  107. #define IDC_DIRECTIONAL_SCALER   17
  108. #define IDC_ENVIRONMENT_BLEND_SCALER 18
  109. #define IDC_ENVIRONMENT_A        19
  110. #define IDC_ENVIRONMENT_B        20
  111.  
  112. #define IDC_RENDER_UI            21
  113. #define IDC_RENDER_MAP           22
  114. #define IDC_RENDER_ARROWS        23
  115. #define IDC_RENDER_MESH          24
  116. #define IDC_SIM_STATUS           25
  117. #define IDC_SIM_STATUS_2         26
  118.  
  119. #define IDC_NUM_PCA              27
  120. #define IDC_NUM_PCA_TEXT         28
  121. #define IDC_NUM_CLUSTERS         29
  122. #define IDC_NUM_CLUSTERS_TEXT    30
  123. #define IDC_MAX_CONSTANTS        31
  124. #define IDC_CUR_CONSTANTS        32
  125. #define IDC_CUR_CONSTANTS_STATIC 34
  126.  
  127. #define IDC_APPLY                33
  128. #define IDC_LIGHT_ANGLE_STATIC   35
  129. #define IDC_LIGHT_ANGLE          36
  130. #define IDC_RENDER_TEXTURE       37
  131. #define IDC_WIREFRAME            38
  132. #define IDC_RESTART              40
  133. #define IDC_COMPRESSION          41
  134. #define IDC_SH_PROJECTION        42
  135.  
  136. #define IDC_TECHNIQUE_PRT        43
  137. #define IDC_TECHNIQUE_SHIRRAD    44
  138. #define IDC_TECHNIQUE_NDOTL      45
  139.  
  140. #define IDC_SCENE_1              46
  141. #define IDC_SCENE_2              47
  142. #define IDC_SCENE_3              48
  143. #define IDC_SCENE_4              49
  144. #define IDC_SCENE_5              50
  145.  
  146.  
  147.  
  148. //--------------------------------------------------------------------------------------
  149. // Forward declarations 
  150. //--------------------------------------------------------------------------------------
  151. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  152. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  153. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  154. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  155. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  156. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  157. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  158. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  159. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  160. void    CALLBACK OnLostDevice();
  161. void    CALLBACK OnDestroyDevice();
  162.  
  163. void    InitApp();
  164. void    RenderText();
  165. void    UpdateLightingEnvironment();
  166. void    UpdateConstText();
  167. void    LoadScene( IDirect3DDevice9* pd3dDevice, WCHAR* strInputMesh, WCHAR* strResultsFile );
  168. void    LoadSceneAndOptGenResults( IDirect3DDevice9* pd3dDevice, WCHAR* strInputMesh, WCHAR* strResultsFile, int nNumRays, int nNumBounces, bool bSubSurface );
  169.  
  170.  
  171. //--------------------------------------------------------------------------------------
  172. // Entry point to the program. Initializes everything and goes into a message processing 
  173. // loop. Idle time is used to render the scene.
  174. //--------------------------------------------------------------------------------------
  175. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  176. {
  177.     // Set the callback functions. These functions allow the sample framework to notify
  178.     // the application about device changes, user input, and windows messages.  The 
  179.     // callbacks are optional so you need only set callbacks for events you're interested 
  180.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  181.     // framework won't be able to reset your device since the application must first 
  182.     // release all device resources before resetting.  Likewise, if you don't handle the 
  183.     // device created/destroyed callbacks then the sample framework won't be able to 
  184.     // recreate your device resources.
  185.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  186.     DXUTSetCallbackDeviceReset( OnResetDevice );
  187.     DXUTSetCallbackDeviceLost( OnLostDevice );
  188.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  189.     DXUTSetCallbackMsgProc( MsgProc );
  190.     DXUTSetCallbackKeyboard( KeyboardProc );
  191.     DXUTSetCallbackFrameRender( OnFrameRender );
  192.     DXUTSetCallbackFrameMove( OnFrameMove );
  193.  
  194.     // Show the cursor and clip it when in full screen
  195.     DXUTSetCursorSettings( true, true );
  196.  
  197.     InitApp();
  198.  
  199.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  200.     // device for the application. Calling each of these functions is optional, but they
  201.     // allow you to set several options which control the behavior of the framework.
  202.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  203.     DXUTCreateWindow( L"PRTPerVertex" );
  204.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 800, 600, IsDeviceAcceptable, ModifyDeviceSettings );
  205.  
  206.     // Pass control to the sample framework for handling the message pump and 
  207.     // dispatching render calls. The sample framework will call your FrameMove 
  208.     // and FrameRender callback when there is idle time between handling window messages.
  209.     DXUTMainLoop();
  210.  
  211.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  212.     // appropriate callback functions and therefore don't require any cleanup code here.
  213.  
  214.     return DXUTGetExitCode();
  215. }
  216.  
  217.  
  218. //--------------------------------------------------------------------------------------
  219. struct SHCubeProj 
  220. {
  221.     float *pRed,*pGreen,*pBlue;
  222.     int iOrderUse; // order to use
  223.     float fConvCoeffs[6]; // convolution coefficients
  224.  
  225.     void InitDiffCubeMap(float *pR, float *pG, float *pB)
  226.     {
  227.         pRed = pR;
  228.         pGreen = pG;
  229.         pBlue = pB;
  230.  
  231.         iOrderUse = 3; // go to 5 is a bit more accurate...
  232.         fConvCoeffs[0] = 1.0f;
  233.         fConvCoeffs[1] = 2.0f/3.0f;
  234.         fConvCoeffs[2] = 1.0f/4.0f;
  235.         fConvCoeffs[3] = fConvCoeffs[5] = 0.0f;
  236.         fConvCoeffs[4] = -6.0f/144.0f; // 
  237.     }
  238.  
  239.     void Init(float *pR, float *pG, float *pB)
  240.     {
  241.         pRed = pR;
  242.         pGreen = pG;
  243.         pBlue = pB;
  244.  
  245.         iOrderUse = 6;
  246.         for(int i=0;i<6;i++) fConvCoeffs[i] = 1.0f;
  247.     }
  248. };
  249.  
  250.  
  251. //--------------------------------------------------------------------------------------
  252. void WINAPI SHCubeFill(D3DXVECTOR4* pOut, 
  253.                        CONST D3DXVECTOR3* pTexCoord, 
  254.                        CONST D3DXVECTOR3* pTexelSize, 
  255.                        LPVOID pData)
  256. {
  257.     SHCubeProj* pCP = (SHCubeProj*) pData;
  258.     D3DXVECTOR3 vDir;
  259.  
  260.     D3DXVec3Normalize(&vDir,pTexCoord);
  261.  
  262.     float fVals[36];
  263.     D3DXSHEvalDirection( fVals, pCP->iOrderUse, &vDir );
  264.  
  265.     (*pOut) = D3DXVECTOR4(0,0,0,0); // just clear it out...
  266.  
  267.     int l, m, uIndex = 0;
  268.     for( l=0; l<pCP->iOrderUse; l++ ) 
  269.     {
  270.         const float fConvUse = pCP->fConvCoeffs[l];
  271.         for( m=0; m<2*l+1; m++ ) 
  272.         {
  273.             pOut->x += fConvUse*fVals[uIndex]*pCP->pRed[uIndex];
  274.             pOut->y += fConvUse*fVals[uIndex]*pCP->pGreen[uIndex];
  275.             pOut->z += fConvUse*fVals[uIndex]*pCP->pBlue[uIndex];
  276.             pOut->w = 1;
  277.  
  278.             uIndex++;
  279.         }
  280.     }
  281. }
  282.  
  283.  
  284. //--------------------------------------------------------------------------------------
  285. // Initialize the app 
  286. //--------------------------------------------------------------------------------------
  287. void InitApp()
  288. {
  289.     for( int i=0; i<MAX_LIGHTS; i++ )
  290.     {
  291.         g_LightControl[i].SetLightDirection( D3DXVECTOR3( sinf(D3DX_PI*2*i/MAX_LIGHTS-D3DX_PI/6), 0, -cosf(D3DX_PI*2*i/MAX_LIGHTS-D3DX_PI/6) ) );
  292.         g_LightControl[i].SetButtonMask( MOUSE_MIDDLE_BUTTON );
  293.     }
  294.  
  295.     g_nActiveLight = 0;
  296.     g_nNumActiveLights = 1;
  297.  
  298.     // Initialize dialogs
  299.     g_HUD.SetCallback( OnGUIEvent ); int iY = 10; 
  300.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
  301.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 );
  302.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22 );
  303.  
  304.     // Title font for comboboxes
  305.     g_StartUpUI.SetFont( 1, L"Arial", 24, FW_BOLD );
  306.     CDXUTElement* pElement = g_StartUpUI.GetDefaultElement( DXUT_CONTROL_STATIC, 0 );
  307.     pElement->iFont = 1;
  308.     pElement->dwTextFormat = DT_CENTER | DT_BOTTOM;
  309.  
  310.     g_StartUpUI.SetCallback( OnGUIEvent ); iY = 10; 
  311.     g_StartUpUI.AddStatic( -1, L"What would you like to do?", 0, 10, 300, 22 );
  312.     g_StartUpUI.AddButton( IDC_SIMULATOR, L"Run PRT simulator", 90, 42, 125, 40 );
  313.     g_StartUpUI.AddButton( IDC_LOAD_PRTBUFFER, L"View saved results", 90, 84, 125, 40 );
  314.  
  315.     g_StartUpUI2.SetCallback( OnGUIEvent ); iY = 10; 
  316.     g_StartUpUI2.AddButton( IDC_SCENE_1, L"Demo Scene 1 (Z)", 0, iY += 24, 125, 22 );
  317.     g_StartUpUI2.AddButton( IDC_SCENE_2, L"Demo Scene 2 (X)", 0, iY += 24, 125, 22 );
  318.     g_StartUpUI2.AddButton( IDC_SCENE_3, L"Demo Scene 3 (C)", 0, iY += 24, 125, 22 );
  319.     g_StartUpUI2.AddButton( IDC_SCENE_4, L"Demo Scene 4 (V)", 0, iY += 24, 125, 22 );
  320.     g_StartUpUI2.AddButton( IDC_SCENE_5, L"Demo Scene 5 (B)", 0, iY += 24, 125, 22 );
  321.  
  322.     g_SimulatorRunningUI.SetFont( 1, L"Arial", 24, FW_BOLD );
  323.     pElement = g_SimulatorRunningUI.GetDefaultElement( DXUT_CONTROL_STATIC, 0 );
  324.     pElement->iFont = 1;
  325.     pElement->dwTextFormat = DT_CENTER | DT_BOTTOM;
  326.  
  327.     g_SimulatorRunningUI.SetCallback( OnGUIEvent ); iY = 10; 
  328.     g_SimulatorRunningUI.AddStatic( IDC_SIM_STATUS, L"", 0, 0, 600, 22 );
  329.     g_SimulatorRunningUI.AddStatic( IDC_SIM_STATUS_2, L"", 0, 30, 600, 22 );
  330.     g_SimulatorRunningUI.AddButton( IDC_STOP_SIMULATOR, L"Stop PRT simulator", 240, 60, 125, 40 );
  331.  
  332.     // Title font for comboboxes
  333.     g_RenderingUI2.SetFont( 1, L"Arial", 14, FW_BOLD );
  334.     pElement = g_RenderingUI.GetDefaultElement( DXUT_CONTROL_STATIC, 0 );
  335.     pElement->iFont = 1;
  336.     pElement->dwTextFormat = DT_LEFT | DT_BOTTOM;
  337.  
  338.     g_RenderingUI2.SetCallback( OnGUIEvent ); iY = 10; 
  339.     g_RenderingUI2.AddCheckBox( IDC_RENDER_UI, L"Show UI (4)", 35, iY += 24, 125, 22, g_bRenderUI, '4' );
  340.     g_RenderingUI2.AddCheckBox( IDC_RENDER_MAP, L"Background (5)", 35, iY += 24, 125, 22, g_bRenderEnvMap, '5' );
  341.     g_RenderingUI2.AddCheckBox( IDC_RENDER_ARROWS, L"Arrows (6)", 35, iY += 24, 125, 22, g_bRenderArrows, '6' );  
  342.     g_RenderingUI2.AddCheckBox( IDC_RENDER_MESH, L"Mesh (7)", 35, iY += 24, 125, 22, g_bRenderMesh, '7' );   
  343.     g_RenderingUI2.AddCheckBox( IDC_RENDER_TEXTURE, L"Texture (8)", 35, iY += 24, 125, 22, g_bRenderWithAlbedoTexture, '8' );   
  344.     g_RenderingUI2.AddCheckBox( IDC_WIREFRAME, L"Wireframe (W)", 35, iY += 24, 125, 22, g_bWireframe );   
  345.     g_RenderingUI2.AddCheckBox( IDC_SH_PROJECTION, L"SH Projection (H)", 35, iY += 24, 125, 22, g_bRenderSHProjection, 'H' );   
  346.     
  347.     WCHAR sz[100];
  348.  
  349.     iY += 10;
  350.     _snwprintf( sz, 100, L"Light scale: %0.2f", 0.0f ); sz[99] = 0;
  351.     g_RenderingUI2.AddStatic( IDC_LIGHT_SCALE_STATIC, sz, 35, iY += 24, 125, 22 );
  352.     g_RenderingUI2.AddSlider( IDC_LIGHT_SCALE, 50, iY += 24, 100, 22, 0, 200, (int)(g_fLightScaleForPRT * 100.0f) );
  353.  
  354.     _snwprintf( sz, 100, L"# Lights: %d", g_nNumActiveLights ); sz[99] = 0;
  355.     g_RenderingUI2.AddStatic( IDC_NUM_LIGHTS_STATIC, sz, 35, iY += 24, 125, 22 );
  356.     g_RenderingUI2.AddSlider( IDC_NUM_LIGHTS, 50, iY += 24, 100, 22, 1, MAX_LIGHTS, g_nNumActiveLights );
  357.  
  358.     _snwprintf( sz, 100, L"Cone Angle: 45" ); sz[99] = 0;
  359.     g_RenderingUI2.AddStatic( IDC_LIGHT_ANGLE_STATIC, sz, 35, iY += 24, 125, 22 );
  360.     g_RenderingUI2.AddSlider( IDC_LIGHT_ANGLE, 50, iY += 24, 100, 22, 1, 180, 45 );
  361.  
  362.     iY += 5;
  363.     g_RenderingUI2.AddButton( IDC_ACTIVE_LIGHT, L"Change active light (K)", 35, iY += 24, 125, 22, 'K' );
  364.  
  365.     iY += 5;
  366.     g_RenderingUI2.AddButton( IDC_COMPRESSION, L"Compression Settings", 35, iY += 24, 125, 22 );
  367.  
  368.     iY += 5;
  369.     g_RenderingUI2.AddButton( IDC_RESTART, L"Restart", 35, iY += 24, 125, 22 );
  370.  
  371.     bool bEnable = (g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->GetValue() != 0 );
  372.     g_RenderingUI2.GetSlider( IDC_LIGHT_ANGLE )->SetEnabled( bEnable );
  373.     g_RenderingUI2.GetSlider( IDC_NUM_LIGHTS )->SetEnabled( bEnable );
  374.     g_RenderingUI2.GetStatic( IDC_LIGHT_ANGLE_STATIC )->SetEnabled( bEnable );
  375.     g_RenderingUI2.GetStatic( IDC_NUM_LIGHTS_STATIC )->SetEnabled( bEnable );
  376.     g_RenderingUI2.GetButton( IDC_ACTIVE_LIGHT )->SetEnabled( bEnable );
  377.  
  378.     // Title font for comboboxes
  379.     g_RenderingUI3.SetFont( 1, L"Arial", 14, FW_BOLD );
  380.     pElement = g_RenderingUI3.GetDefaultElement( DXUT_CONTROL_STATIC, 0 );
  381.     pElement->iFont = 1;
  382.     pElement->dwTextFormat = DT_LEFT | DT_BOTTOM;
  383.  
  384.     g_RenderingUI3.SetCallback( OnGUIEvent ); iY = 0; 
  385.     g_RenderingUI3.AddStatic( IDC_STATIC, L"(T)echnique", 0, iY, 150, 25 );
  386.     g_RenderingUI3.AddRadioButton( IDC_TECHNIQUE_PRT, 1, L"(1) PRT", 0, iY += 24, 150, 22, true, '1' );   
  387.     g_RenderingUI3.AddRadioButton( IDC_TECHNIQUE_SHIRRAD, 1, L"(2) SHIrradEnvMap", 0, iY += 24, 150, 22, false, '2' );   
  388.     g_RenderingUI3.AddRadioButton( IDC_TECHNIQUE_NDOTL, 1, L"(3) N dot L", 0, iY += 24, 150, 22, false, '3' );   
  389.  
  390.     // Title font for comboboxes
  391.     g_RenderingUI.SetFont( 1, L"Arial", 14, FW_BOLD );
  392.     pElement = g_RenderingUI.GetDefaultElement( DXUT_CONTROL_STATIC, 0 );
  393.     pElement->iFont = 1;
  394.     pElement->dwTextFormat = DT_LEFT | DT_BOTTOM;
  395.  
  396.     g_RenderingUI.SetCallback( OnGUIEvent ); 
  397.  
  398.     int iStartY = 0;
  399.     int iX = 10;
  400.     iY = iStartY; 
  401.     g_RenderingUI.AddStatic( IDC_STATIC, L"(F)irst Light Probe", iX, iY += 24, 150, 25 );
  402.     g_RenderingUI.AddComboBox( IDC_ENVIRONMENT_A, iX, iY += 24, 150, 22, 'F' );   
  403.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_A)->SetDropHeight( 30 );
  404.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_A )->AddItem( L"Eucalyptus Grove", (void*)0 );
  405. #if NUM_SKY_BOXES > 1
  406.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_A )->AddItem( L"The Uffizi Gallery", (void*)1 );
  407. #endif
  408. #if NUM_SKY_BOXES > 2
  409.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_A )->AddItem( L"Galileo's Tomb", (void*)2 );
  410. #endif
  411. #if NUM_SKY_BOXES > 3
  412.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_A )->AddItem( L"Grace Cathedral", (void*)3 );
  413. #endif
  414. #if NUM_SKY_BOXES > 4
  415.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_A )->AddItem( L"St. Peter's Basilica", (void*)4 );
  416. #endif
  417.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_A)->SetSelectedByData( IntToPtr(g_dwSkyBoxA) );
  418.     
  419.     g_RenderingUI.AddStatic( IDC_STATIC, L"First Light Probe Scaler", iX, iY += 24, 150, 25 );
  420.     g_RenderingUI.AddSlider( IDC_ENVIRONMENT_1_SCALER, iX, iY += 24, 150, 22, 0, 100, 50 );
  421.  
  422.     iX += 175;
  423.     iY = iStartY + 30; 
  424.     g_RenderingUI.AddStatic( IDC_STATIC, L"Light Probe Blend", iX, iY += 24, 100, 25 );
  425.     g_RenderingUI.AddSlider( IDC_ENVIRONMENT_BLEND_SCALER, iX, iY += 24, 100, 22, 0, 100, 0 );   
  426.  
  427.     iX += 125;
  428.     iY = iStartY; 
  429.     g_RenderingUI.AddStatic( IDC_STATIC, L"(S)econd Light Probe", iX, iY += 24, 150, 25 );
  430.     g_RenderingUI.AddComboBox( IDC_ENVIRONMENT_B, iX, iY += 24, 150, 22, 'S' );   
  431.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_B )->SetDropHeight( 30 );
  432.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_B )->AddItem( L"Eucalyptus Grove", (void*)0 );
  433. #if NUM_SKY_BOXES > 1
  434.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_B )->AddItem( L"The Uffizi Gallery", (void*)1 );
  435. #endif
  436. #if NUM_SKY_BOXES > 2
  437.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_B )->AddItem( L"Galileo's Tomb", (void*)2 );
  438. #endif
  439. #if NUM_SKY_BOXES > 3
  440.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_B )->AddItem( L"Grace Cathedral", (void*)3 );
  441. #endif
  442. #if NUM_SKY_BOXES > 4
  443.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_B )->AddItem( L"St. Peter's Basilica", (void*)4 );
  444. #endif
  445.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_B )->SetSelectedByData( IntToPtr(g_dwSkyBoxB) );
  446.  
  447.     g_RenderingUI.AddStatic( IDC_STATIC, L"Second Light Probe Scaler", iX, iY += 24, 150, 25 );
  448.     g_RenderingUI.AddSlider( IDC_ENVIRONMENT_2_SCALER, iX, iY += 24, 150, 22, 0, 100, 50 );
  449.  
  450.     g_CompressionUI.SetCallback( OnGUIEvent ); iY = 10;
  451.  
  452.     SIMULATOR_OPTIONS& options = GetGlobalOptions();
  453.  
  454.     g_CompressionUI.AddStatic( IDC_NUM_PCA_TEXT, L"Number of PCA: 24", 30, iY += 24, 120, 22 );
  455.     g_CompressionUI.AddSlider( IDC_NUM_PCA, 30, iY += 24, 120, 22, 1, 6, options.dwNumPCA/4 );
  456.     g_CompressionUI.AddStatic( IDC_NUM_CLUSTERS_TEXT, L"Number of Clusters: 1", 30, iY += 24, 120, 22 );
  457.     g_CompressionUI.AddSlider( IDC_NUM_CLUSTERS, 30, iY += 24, 120, 22, 1, 40, options.dwNumClusters );
  458.     g_CompressionUI.AddStatic( IDC_MAX_CONSTANTS, L"Max VS Constants: 0", 30, iY += 24, 120, 22 );
  459.     g_CompressionUI.AddStatic( IDC_CUR_CONSTANTS_STATIC, L"Cur VS Constants:", 30, iY += 24, 120, 22 );
  460.     g_CompressionUI.AddStatic( IDC_CUR_CONSTANTS, L"0", -10, iY += 12, 200, 22 );
  461.     g_CompressionUI.AddButton( IDC_APPLY, L"Apply", 30, iY += 24, 120, 24 );
  462.  
  463.     swprintf( sz, L"Number of PCA: %d", options.dwNumPCA );
  464.     g_CompressionUI.GetStatic( IDC_NUM_PCA_TEXT )->SetText( sz );           
  465.     swprintf( sz, L"Number of Clusters: %d", options.dwNumClusters );
  466.     g_CompressionUI.GetStatic( IDC_NUM_CLUSTERS_TEXT )->SetText( sz );           
  467.     UpdateConstText();
  468. }
  469.  
  470.  
  471. //--------------------------------------------------------------------------------------
  472. // Called during device initialization, this code checks the device for some 
  473. // minimum set of capabilities, and rejects those that don't pass by returning false.
  474. //--------------------------------------------------------------------------------------
  475. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  476.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  477. {
  478.     // Skip backbuffer formats that don't support alpha blending
  479.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  480.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  481.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  482.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  483.         return false;
  484.  
  485.     return true;
  486. }
  487.  
  488.  
  489. //--------------------------------------------------------------------------------------
  490. // This callback function is called immediately before a device is created to allow the 
  491. // application to modify the device settings. The supplied pDeviceSettings parameter 
  492. // contains the settings that the framework has selected for the new device, and the 
  493. // application can make any desired changes directly to this structure.  Note however that 
  494. // the sample framework will not correct invalid device settings so care must be taken 
  495. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  496. //--------------------------------------------------------------------------------------
  497. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  498. {
  499.     // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  500.     // then switch to SWVP.
  501.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  502.          pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  503.     {
  504.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  505.     }
  506.     else
  507.     {
  508.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  509.     }
  510.  
  511.     // The PRT simulator runs on a seperate thread.  If you are just 
  512.     // loading simulator results, then this isn't needed
  513.     pDeviceSettings->BehaviorFlags |= D3DCREATE_MULTITHREADED;
  514.  
  515.     // This application is designed to work on a pure device by not using 
  516.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  517.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  518.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  519.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  520.  
  521.     // Debugging vertex shaders requires either REF or software vertex processing 
  522.     // and debugging pixel shaders requires REF.  
  523. #ifdef DEBUG_VS
  524.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  525.     {
  526.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  527.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE;
  528.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  529.     }
  530. #endif
  531. #ifdef DEBUG_PS
  532.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  533. #endif
  534. }
  535.  
  536.  
  537. //--------------------------------------------------------------------------------------
  538. // This callback function will be called immediately after the Direct3D device has been 
  539. // created, which will happen during application initialization and windowed/full screen 
  540. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  541. // resources need to be reloaded whenever the device is destroyed. Resources created  
  542. // here should be released in the OnDestroyDevice callback. 
  543. //--------------------------------------------------------------------------------------
  544. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  545. {
  546.     HRESULT hr;
  547.     WCHAR* str;
  548.  
  549.     for(int i=0; i<NUM_SKY_BOXES; ++i )
  550.     {
  551.         switch( i )
  552.         {
  553.             case 0: str = L"Light Probes\\rnl_cross.dds"; break;
  554.             case 1: str = L"Light Probes\\uffizi_cross.dds"; break;
  555.             case 2: str = L"Light Probes\\galileo_cross.dds"; break;
  556.             case 3: str = L"Light Probes\\grace_cross.dds"; break;
  557.             case 4: 
  558.             default: str = L"Light Probes\\stpeters_cross.dds"; break;
  559.         }
  560.  
  561.         g_Skybox[i].OnCreateDevice( pd3dDevice, 50, str, L"SkyBox.fx" );
  562.  
  563.         V( D3DXSHProjectCubeMap( 6, g_Skybox[i].GetEnvironmentMap(), g_fSkyBoxLightSH[i][0], g_fSkyBoxLightSH[i][1], g_fSkyBoxLightSH[i][2] ) );
  564.  
  565.         // now compute the SH projection of the skybox...
  566.         LPDIRECT3DCUBETEXTURE9 pSHCubeTex=NULL;
  567.         V( D3DXCreateCubeTexture( pd3dDevice, 256, 1, 0, D3DFMT_A16B16G16R16F, D3DPOOL_MANAGED, &pSHCubeTex ) );
  568.  
  569.         SHCubeProj projData;
  570.         projData.Init(g_fSkyBoxLightSH[i][0],g_fSkyBoxLightSH[i][1],g_fSkyBoxLightSH[i][2]);
  571.  
  572.         V( D3DXFillCubeTexture(pSHCubeTex,SHCubeFill,&projData));
  573. /*
  574.         switch( i )
  575.         {
  576.             case 0: str = L"diff_rnl_cross.dds"; break;
  577.             case 1: str = L"diff_uffizi_cross.dds"; break;
  578.             case 2: str = L"diff_galileo_cross.dds"; break;
  579.             case 3: str = L"diff_grace_cross.dds"; break;
  580.             case 4: 
  581.             default: str = L"diff_stpeters_cross.dds"; break;
  582.         }
  583.         V( D3DXSaveTextureToFile( str, D3DXIFF_DDS, pSHCubeTex, NULL ) ); 
  584. */
  585.         g_Skybox[i].InitSH(pSHCubeTex);
  586.     }
  587.  
  588.     V_RETURN( g_PRTMesh.OnCreateDevice( pd3dDevice ) );
  589.  
  590.     // Initialize the font
  591.     V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, 
  592.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  593.                          L"Arial", &g_pFont ) );
  594.     V_RETURN( CDXUTDirectionWidget::StaticOnCreateDevice( pd3dDevice ) );
  595.  
  596.     // Setup the camera's view parameters
  597.     D3DXVECTOR3 vecEye(0.0f, 0.0f, -5.0f);
  598.     D3DXVECTOR3 vecAt (0.0f, 0.0f, -0.0f);
  599.     g_Camera.SetViewParams( &vecEye, &vecAt );
  600.  
  601.     DWORD dwMaxVertexShaderConst = DXUTGetDeviceCaps()->MaxVertexShaderConst;
  602.     WCHAR sz[256];
  603.     int nMax = (dwMaxVertexShaderConst - 4) / 2;
  604.     g_CompressionUI.GetSlider( IDC_NUM_CLUSTERS )->SetRange( 1, nMax );
  605.  
  606.     swprintf( sz, L"Max VS Constants: %d", dwMaxVertexShaderConst );
  607.     g_CompressionUI.GetStatic( IDC_MAX_CONSTANTS )->SetText( sz );
  608.     UpdateConstText();
  609.  
  610.     return S_OK;
  611. }
  612.  
  613.  
  614. //--------------------------------------------------------------------------------------
  615. // This callback function will be called immediately after the Direct3D device has been 
  616. // reset, which will happen after a lost device scenario. This is the best location to 
  617. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  618. // the device is lost. Resources created here should be released in the OnLostDevice 
  619. // callback. 
  620. //--------------------------------------------------------------------------------------
  621. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  622.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  623. {
  624.     HRESULT hr;
  625.  
  626.     for(int i=0; i<NUM_SKY_BOXES; ++i )
  627.         g_Skybox[i].OnResetDevice( pBackBufferSurfaceDesc ); 
  628.  
  629.     V( g_PRTMesh.OnResetDevice() );
  630.  
  631.     if( g_pFont )
  632.         V( g_pFont->OnResetDevice() );
  633.  
  634.     // Create a sprite to help batch calls when drawing many lines of text
  635.     V( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );
  636.  
  637.     for( int i=0; i<MAX_LIGHTS; i++ )
  638.         g_LightControl[i].OnResetDevice( pBackBufferSurfaceDesc  );
  639.  
  640.     // Setup the camera's projection parameters
  641.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  642.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 1.0f, 10000.0f );
  643.     g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
  644.     g_Camera.SetButtonMasks( MOUSE_LEFT_BUTTON, MOUSE_WHEEL, MOUSE_RIGHT_BUTTON );
  645.     g_Camera.SetAttachCameraToModel( true );
  646.  
  647.     if( g_PRTMesh.GetMesh() != NULL )
  648.     {
  649.         // Update camera's viewing radius based on the object radius
  650.         float fObjectRadius = g_PRTMesh.GetObjectRadius();
  651.         if( g_fCurObjectRadius != fObjectRadius )
  652.         {
  653.             g_fCurObjectRadius = fObjectRadius;
  654.             g_Camera.SetRadius( fObjectRadius*3.0f, fObjectRadius*0.1f, fObjectRadius*20.0f );
  655.         }
  656.         g_Camera.SetModelCenter( g_PRTMesh.GetObjectCenter() );
  657.         for( int i=0; i<MAX_LIGHTS; i++ )
  658.             g_LightControl[i].SetRadius(fObjectRadius);
  659.     }
  660.  
  661.     g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
  662.     g_HUD.SetSize( 170, 100 );
  663.     g_StartUpUI.SetLocation( (pBackBufferSurfaceDesc->Width-300)/2, (pBackBufferSurfaceDesc->Height-200)/2 );
  664.     g_StartUpUI.SetSize( 300, 200 );
  665.     g_StartUpUI2.SetLocation( 50, (pBackBufferSurfaceDesc->Height-200) );
  666.     g_StartUpUI2.SetSize( 300, 200 );
  667.     g_CompressionUI.SetLocation( 0, 150 );
  668.     g_CompressionUI.SetSize( 200, 200 );
  669.     g_SimulatorRunningUI.SetLocation( (pBackBufferSurfaceDesc->Width-600)/2, (pBackBufferSurfaceDesc->Height-100)/2 );
  670.     g_SimulatorRunningUI.SetSize( 600, 100 );
  671.     g_RenderingUI.SetLocation( 0, pBackBufferSurfaceDesc->Height-125 );
  672.     g_RenderingUI.SetSize( pBackBufferSurfaceDesc->Width, 125 );
  673.     g_RenderingUI2.SetLocation( pBackBufferSurfaceDesc->Width-170, 100 );
  674.     g_RenderingUI2.SetSize( 170, 400 );
  675.     g_RenderingUI3.SetLocation( 10, 30 );
  676.     g_RenderingUI3.SetSize( 200, 100 );
  677.  
  678.     return S_OK;
  679. }
  680.  
  681.  
  682. //--------------------------------------------------------------------------------------
  683. // This callback function will be called once at the beginning of every frame. This is the
  684. // best location for your application to handle updates to the scene, but is not 
  685. // intended to contain actual rendering calls, which should instead be placed in the 
  686. // OnFrameRender callback.  
  687. //--------------------------------------------------------------------------------------
  688. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  689. {
  690.     // Update the camera's position based on user input 
  691.     g_Camera.FrameMove( fElapsedTime );
  692. }
  693.  
  694.  
  695. //--------------------------------------------------------------------------------------
  696. void RenderStartup( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  697. {
  698.     HRESULT hr;
  699.     
  700.     // Clear the render target and the zbuffer 
  701.     V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );
  702.  
  703.     // Render the scene
  704.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  705.     {
  706.         RenderText();
  707.         if( g_bRenderUI )
  708.         {
  709.             D3DXMATRIXA16 mWorld;
  710.             D3DXMATRIXA16 mView;
  711.             D3DXMATRIXA16 mProj;
  712.             D3DXMATRIXA16 mWorldViewProjection;
  713.             D3DXMATRIXA16 mViewProjection;
  714.             mWorld = *g_Camera.GetWorldMatrix();       
  715.             mProj = *g_Camera.GetProjMatrix();       
  716.             mView = *g_Camera.GetViewMatrix();
  717.             mViewProjection = mView * mProj;        
  718.  
  719.             V( g_HUD.OnRender( fElapsedTime ) );
  720.             V( g_StartUpUI.OnRender( fElapsedTime ) );
  721.             V( g_StartUpUI2.OnRender( fElapsedTime ) );
  722.         }
  723.  
  724.         V( pd3dDevice->EndScene() );
  725.     }
  726. }
  727.  
  728.  
  729. //--------------------------------------------------------------------------------------
  730. void RenderSimulatorRunning( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  731. {
  732.     HRESULT hr;
  733.     
  734.     // Clear the render target and the zbuffer 
  735.     V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );
  736.  
  737.     // Render the scene
  738.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  739.     {
  740.         RenderText();
  741.         V( g_SimulatorRunningUI.OnRender( fElapsedTime ) );
  742.  
  743.         V( pd3dDevice->EndScene() );
  744.     }
  745. }
  746.  
  747.  
  748. //--------------------------------------------------------------------------------------
  749. void RenderPRT( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  750. {
  751.     HRESULT hr;
  752.     D3DXMATRIXA16 mWorld;
  753.     D3DXMATRIXA16 mView;
  754.     D3DXMATRIXA16 mProj;
  755.     D3DXMATRIXA16 mWorldViewProjection;
  756.     D3DXMATRIXA16 mViewProjection;
  757.     
  758.     pd3dDevice->SetRenderState( D3DRS_FILLMODE, (g_bWireframe) ? D3DFILL_WIREFRAME : D3DFILL_SOLID ); 
  759.  
  760.     // Clear the render target and the zbuffer 
  761. //    V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );
  762.     V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0) );
  763.  
  764.     // Render the scene
  765.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  766.     {
  767.         mWorld = *g_Camera.GetWorldMatrix();       
  768.         mProj = *g_Camera.GetProjMatrix();       
  769.         mView = *g_Camera.GetViewMatrix();
  770.  
  771.         mWorldViewProjection = mWorld * mView * mProj;
  772.  
  773.         if( g_bRenderEnvMap && !g_bWireframe )
  774.         {
  775.             float fEnv1Scaler = (g_RenderingUI.GetSlider( IDC_ENVIRONMENT_1_SCALER )->GetValue() / 100.0f);
  776.             float fEnv2Scaler = (g_RenderingUI.GetSlider( IDC_ENVIRONMENT_2_SCALER )->GetValue() / 100.0f);
  777.  
  778.             float fEnvBlendScaler = (g_RenderingUI.GetSlider( IDC_ENVIRONMENT_BLEND_SCALER )->GetValue() / 100.0f);
  779.             pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  780.             pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  781.             pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
  782.  
  783.             g_Skybox[g_dwSkyBoxA].SetDrawSH( g_bRenderSHProjection );
  784.             g_Skybox[g_dwSkyBoxB].SetDrawSH( g_bRenderSHProjection );
  785.  
  786.             mViewProjection = mView * mProj;        
  787.             g_Skybox[g_dwSkyBoxA].Render( &mViewProjection, (1.0f-fEnvBlendScaler), fEnv1Scaler );
  788.             g_Skybox[g_dwSkyBoxB].Render( &mViewProjection, (fEnvBlendScaler), fEnv2Scaler );
  789.  
  790.             pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  791.         }
  792.  
  793.         float fLightScale = (float) (g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->GetValue() * 0.01f);
  794.         if( g_bRenderArrows && fLightScale > 0.0f )
  795.         {
  796.             // Render the light spheres so the user can 
  797.             // visually see the light dir
  798.             for( int i=0; i<g_nNumActiveLights; i++ )
  799.             {
  800.                 D3DXCOLOR arrowColor = ( i == g_nActiveLight ) ? D3DXCOLOR(1,1,0,1) : D3DXCOLOR(1,1,1,1);
  801.                 V( g_LightControl[i].OnRender( arrowColor, &mView, &mProj, g_Camera.GetEyePt() ) );
  802.             }
  803.         }
  804.  
  805.         if( g_bRenderMesh )
  806.         {
  807.             switch( g_dwTechnique )
  808.             {
  809.                 case 0: // PRT
  810.                     g_PRTMesh.RenderWithPRT( pd3dDevice, &mWorldViewProjection, g_bRenderWithAlbedoTexture );
  811.                     break;
  812.  
  813.                 case 1: // SHIrradEnvMap
  814.                     g_PRTMesh.RenderWithSHIrradEnvMap( pd3dDevice, &mWorldViewProjection, g_bRenderWithAlbedoTexture );
  815.                     break;
  816.  
  817.                 case 2: // N dot L
  818.                 {
  819.                     D3DXMATRIX mWorldInv;
  820.                     D3DXMatrixInverse(&mWorldInv, NULL, g_Camera.GetWorldMatrix() );
  821.                     g_PRTMesh.RenderWithNdotL( pd3dDevice, &mWorldViewProjection, &mWorldInv, g_bRenderWithAlbedoTexture, g_LightControl, g_nNumActiveLights, fLightScale );
  822.                     break;
  823.                 }
  824.             }
  825.  
  826.  
  827.         }
  828.  
  829.         RenderText();
  830.         if( g_bRenderUI )
  831.         {
  832.             V( g_HUD.OnRender( fElapsedTime ) );
  833.             V( g_RenderingUI.OnRender( fElapsedTime ) );
  834.             V( g_RenderingUI2.OnRender( fElapsedTime ) );
  835.             V( g_RenderingUI3.OnRender( fElapsedTime ) );
  836.             if( g_bRenderCompressionUI )
  837.                 V( g_CompressionUI.OnRender( fElapsedTime ) );
  838.         }
  839.  
  840.         V( pd3dDevice->EndScene() );
  841.     }
  842. }
  843.  
  844.  
  845. //--------------------------------------------------------------------------------------
  846. // This callback function will be called at the end of every frame to perform all the 
  847. // rendering calls for the scene, and it will also be called if the window needs to be 
  848. // repainted. After this function has returned, the sample framework will call 
  849. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  850. //--------------------------------------------------------------------------------------
  851. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  852. {
  853.     switch( g_AppState )
  854.     {
  855.         case APP_STATE_STARTUP: 
  856.             RenderStartup( pd3dDevice, fTime, fElapsedTime ); 
  857.             break;
  858.  
  859.         case APP_STATE_SIMULATOR_OPTIONS:
  860.         {
  861.             CPRTOptionsDlg dlg;
  862.  
  863.             bool bFullscreenToggle = false;
  864.             if( !DXUTIsWindowed() )
  865.             {
  866.                 if( SUCCEEDED( DXUTToggleFullScreen() ) )
  867.                     bFullscreenToggle = true;
  868.             }
  869.  
  870.             bool bResult = dlg.Show();
  871.  
  872.             if( bFullscreenToggle )
  873.                 DXUTToggleFullScreen();
  874.  
  875.             if( bResult )
  876.             {                
  877.                 SIMULATOR_OPTIONS* pOptions = dlg.GetOptions();
  878.                 g_PRTMesh.LoadMesh( pd3dDevice, pOptions->strInputMesh );
  879.  
  880.                 // Update camera's viewing radius based on the object radius
  881.                 float fObjectRadius = g_PRTMesh.GetObjectRadius();
  882.                 if( g_fCurObjectRadius != fObjectRadius )
  883.                 {
  884.                     g_fCurObjectRadius = fObjectRadius;
  885.                     g_Camera.SetRadius( fObjectRadius*3.0f, fObjectRadius*0.1f, fObjectRadius*20.0f );
  886.                 }
  887.                 g_Camera.SetModelCenter( g_PRTMesh.GetObjectCenter() );
  888.                 for( int i=0; i<MAX_LIGHTS; i++ )
  889.                     g_LightControl[i].SetRadius(fObjectRadius);
  890.  
  891.                 g_Simulator.Run( pd3dDevice, pOptions, &g_PRTMesh );
  892.                 g_AppState = APP_STATE_SIMULATOR_RUNNING;
  893.             }
  894.             else
  895.             {
  896.                 g_AppState = APP_STATE_STARTUP;                
  897.             }
  898.             break;
  899.         }
  900.  
  901.         case APP_STATE_SIMULATOR_RUNNING:
  902.         {
  903.             WCHAR sz[256];
  904.             if( g_Simulator.GetPercentComplete() >= 0.0f )
  905.                 swprintf( sz, L"Step %d of %d: %0.1f%% done", g_Simulator.GetCurrentPass(), g_Simulator.GetNumPasses(), g_Simulator.GetPercentComplete() );
  906.             else
  907.                 swprintf( sz, L"Step %d of %d (progress n/a)", g_Simulator.GetCurrentPass(), g_Simulator.GetNumPasses() );
  908.             g_SimulatorRunningUI.GetStatic( IDC_SIM_STATUS )->SetText( sz );
  909.             g_SimulatorRunningUI.GetStatic( IDC_SIM_STATUS_2 )->SetText( g_Simulator.GetCurrentPassName() );
  910.  
  911.             RenderSimulatorRunning( pd3dDevice, fTime, fElapsedTime );
  912.             Sleep(50); // Yield time to simulator thread
  913.  
  914.             if( !g_Simulator.IsRunning() )
  915.             {
  916.                 g_PRTMesh.LoadEffects( pd3dDevice, DXUTGetDeviceCaps() );
  917.                 DXUTSetMultimonSettings( true );
  918.                 g_AppState = APP_STATE_RENDER_SCENE;                
  919.                 g_bRenderCompressionUI = false;
  920.             }
  921.             break;
  922.         }
  923.            
  924.         case APP_STATE_LOAD_PRT_BUFFER:
  925.         {
  926.             CPRTLoadDlg dlg;
  927.             bool bResult = dlg.Show();
  928.             if( bResult )
  929.             {
  930.                 SIMULATOR_OPTIONS* pOptions = dlg.GetOptions();
  931.                 if( !pOptions->bAdaptive )
  932.                     LoadScene( pd3dDevice, pOptions->strInputMesh, pOptions->strResultsFile );
  933.                 else
  934.                     LoadScene( pd3dDevice, pOptions->strOutputMesh, pOptions->strResultsFile );
  935.             }
  936.             else
  937.             {
  938.                 g_AppState = APP_STATE_STARTUP;                
  939.             }
  940.             break;
  941.         }
  942.  
  943.         case APP_STATE_RENDER_SCENE: 
  944.             UpdateLightingEnvironment();
  945.             RenderPRT( pd3dDevice, fTime, fElapsedTime ); 
  946.             break;
  947.     
  948.         default:
  949.             assert(false);
  950.             break;
  951.     }
  952. }
  953.  
  954.  
  955. //--------------------------------------------------------------------------------------
  956. void UpdateLightingEnvironment()
  957. {
  958.     HRESULT hr;
  959.  
  960.     float fEnv1Scaler = (g_RenderingUI.GetSlider( IDC_ENVIRONMENT_1_SCALER )->GetValue() / 100.0f);
  961.     float fEnv2Scaler = (g_RenderingUI.GetSlider( IDC_ENVIRONMENT_2_SCALER )->GetValue() / 100.0f);
  962.     float fEnvBlendScaler = (g_RenderingUI.GetSlider( IDC_ENVIRONMENT_BLEND_SCALER )->GetValue() / 100.0f);
  963.     float fLightScale = (float) (g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->GetValue() * 0.01f);
  964.     float fConeRadius = (float) ( ( D3DX_PI * (float)g_RenderingUI2.GetSlider( IDC_LIGHT_ANGLE )->GetValue()) / 180.0f );    
  965.  
  966.     float fLight[MAX_LIGHTS][3][D3DXSH_MAXORDER*D3DXSH_MAXORDER];  
  967.  
  968.     D3DXCOLOR lightColor(1.0f, 1.0f, 1.0f, 1.0f);        
  969.     lightColor *= fLightScale;
  970.  
  971.     DWORD dwOrder = g_PRTMesh.GetOrder();
  972.  
  973.     // Pass in the light direction, the intensity of each channel, and it returns
  974.     // the source radiance as an array of order^2 SH coefficients for each color channel.  
  975.     D3DXVECTOR3 lightDirObjectSpace;
  976.     D3DXMATRIX mWorldInv;
  977.     D3DXMatrixInverse(&mWorldInv, NULL, g_Camera.GetWorldMatrix() );
  978.  
  979.     int i;
  980.     for( i=0; i<g_nNumActiveLights; i++ )
  981.     {
  982.         // Transform the world space light dir into object space
  983.         // Note that if there's multiple objects using PRT in the scene, then
  984.         // for each object you need to either evaulate the lights in object space
  985.         // evaulate the lights in world and rotate the light coefficients 
  986.         // into object space.
  987.         D3DXVECTOR3 vLight = g_LightControl[i].GetLightDirection();
  988.         D3DXVec3TransformNormal( &lightDirObjectSpace, &vLight, &mWorldInv );
  989.  
  990.         // This sample uses D3DXSHEvalDirectionalLight(), but there's other 
  991.         // types of lights provided by D3DXSHEval*.  Pass in the 
  992.         // order of SH, color of the light, and the direction of the light 
  993.         // in object space.
  994.         // The output is the source radiance coefficients for the SH basis functions.  
  995.         // There are 3 outputs, one for each channel (R,G,B). 
  996.         // Each output is an array of m_dwOrder^2 floats.  
  997.         V( D3DXSHEvalConeLight( dwOrder, &lightDirObjectSpace, fConeRadius,
  998.                                 lightColor.r, lightColor.g, lightColor.b,
  999.                                 fLight[i][0], fLight[i][1], fLight[i][2] ) );
  1000.     }
  1001.  
  1002.     float fSum[3][D3DXSH_MAXORDER*D3DXSH_MAXORDER];  
  1003.     ZeroMemory( fSum, 3*D3DXSH_MAXORDER*D3DXSH_MAXORDER*sizeof(float) );
  1004.  
  1005.     // For multiple lights, just them sum up using D3DXSHAdd().
  1006.     for( i=0; i<g_nNumActiveLights; i++ )
  1007.     {
  1008.         // D3DXSHAdd will add Order^2 floats.  There are 3 color channels, 
  1009.         // so call it 3 times.
  1010.         D3DXSHAdd( fSum[0], dwOrder, fSum[0], fLight[i][0] );
  1011.         D3DXSHAdd( fSum[1], dwOrder, fSum[1], fLight[i][1] );
  1012.         D3DXSHAdd( fSum[2], dwOrder, fSum[2], fLight[i][2] );
  1013.     }
  1014.  
  1015.     float fSkybox1[3][D3DXSH_MAXORDER*D3DXSH_MAXORDER];  
  1016.     float fSkybox1Rot[3][D3DXSH_MAXORDER*D3DXSH_MAXORDER];  
  1017.     D3DXSHScale( fSkybox1[0], dwOrder, g_fSkyBoxLightSH[g_dwSkyBoxA][0], fEnv1Scaler*(1.0f-fEnvBlendScaler) );
  1018.     D3DXSHScale( fSkybox1[1], dwOrder, g_fSkyBoxLightSH[g_dwSkyBoxA][1], fEnv1Scaler*(1.0f-fEnvBlendScaler) );
  1019.     D3DXSHScale( fSkybox1[2], dwOrder, g_fSkyBoxLightSH[g_dwSkyBoxA][2], fEnv1Scaler*(1.0f-fEnvBlendScaler) );
  1020.     D3DXSHRotate( fSkybox1Rot[0], dwOrder, &mWorldInv, fSkybox1[0] );
  1021.     D3DXSHRotate( fSkybox1Rot[1], dwOrder, &mWorldInv, fSkybox1[1] );
  1022.     D3DXSHRotate( fSkybox1Rot[2], dwOrder, &mWorldInv, fSkybox1[2] );
  1023.     D3DXSHAdd( fSum[0], dwOrder, fSum[0], fSkybox1Rot[0] );
  1024.     D3DXSHAdd( fSum[1], dwOrder, fSum[1], fSkybox1Rot[1] );
  1025.     D3DXSHAdd( fSum[2], dwOrder, fSum[2], fSkybox1Rot[2] );
  1026.  
  1027.     float fSkybox2[3][D3DXSH_MAXORDER*D3DXSH_MAXORDER];  
  1028.     float fSkybox2Rot[3][D3DXSH_MAXORDER*D3DXSH_MAXORDER];  
  1029.     D3DXSHScale( fSkybox2[0], dwOrder, g_fSkyBoxLightSH[g_dwSkyBoxB][0], fEnv2Scaler*fEnvBlendScaler );
  1030.     D3DXSHScale( fSkybox2[1], dwOrder, g_fSkyBoxLightSH[g_dwSkyBoxB][1], fEnv2Scaler*fEnvBlendScaler );
  1031.     D3DXSHScale( fSkybox2[2], dwOrder, g_fSkyBoxLightSH[g_dwSkyBoxB][2], fEnv2Scaler*fEnvBlendScaler );
  1032.     D3DXSHRotate( fSkybox2Rot[0], dwOrder, &mWorldInv, fSkybox2[0] );
  1033.     D3DXSHRotate( fSkybox2Rot[1], dwOrder, &mWorldInv, fSkybox2[1] );
  1034.     D3DXSHRotate( fSkybox2Rot[2], dwOrder, &mWorldInv, fSkybox2[2] );
  1035.     D3DXSHAdd( fSum[0], dwOrder, fSum[0], fSkybox2Rot[0] );
  1036.     D3DXSHAdd( fSum[1], dwOrder, fSum[1], fSkybox2Rot[1] );
  1037.     D3DXSHAdd( fSum[2], dwOrder, fSum[2], fSkybox2Rot[2] );
  1038.  
  1039.     g_PRTMesh.ComputeShaderConstants( fSum[0], fSum[1], fSum[2], dwOrder*dwOrder );
  1040.     g_PRTMesh.ComputeSHIrradEnvMapConstants( fSum[0], fSum[1], fSum[2] );
  1041. }
  1042.  
  1043. //--------------------------------------------------------------------------------------
  1044. // Render the help and statistics text. This function uses the ID3DXFont interface for 
  1045. // efficient text rendering.
  1046. //--------------------------------------------------------------------------------------
  1047. void RenderText()
  1048. {
  1049.     if( !g_bRenderText ) 
  1050.         return;
  1051.  
  1052.     // The helper object simply helps keep track of text position, and color
  1053.     // and then it calls pFont->DrawText( g_pSprite, strMsg, -1, &rc, DT_NOCLIP, g_clr );
  1054.     // If NULL is passed in as the sprite object, then it will work however the 
  1055.     // pFont->DrawText() will not be batched together.  Batching calls will improves performance.
  1056.     CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
  1057.  
  1058.     // Output statistics
  1059.     txtHelper.Begin();
  1060.     txtHelper.SetInsertionPos( 5, 5 );
  1061.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  1062.     txtHelper.DrawTextLine( DXUTGetFrameStats() );
  1063.     txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  1064.     if( !g_bRenderUI )
  1065.         txtHelper.DrawFormattedTextLine( L"Press '4' to show UI" );
  1066.  
  1067.     txtHelper.End();
  1068. }
  1069.  
  1070.  
  1071. //--------------------------------------------------------------------------------------
  1072. // Before handling window messages, the sample framework passes incoming windows 
  1073. // messages to the application through this callback function. If the application sets 
  1074. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  1075. //--------------------------------------------------------------------------------------
  1076. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  1077. {
  1078.     if( uMsg == WM_KEYDOWN && wParam == VK_F8 )
  1079.         *pbNoFurtherProcessing = true;
  1080.  
  1081.     if( g_AppState != APP_STATE_SIMULATOR_RUNNING )
  1082.     {
  1083.         // Give the dialogs a chance to handle the message first
  1084.         *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  1085.         if( *pbNoFurtherProcessing )
  1086.             return 0;
  1087.     }
  1088.  
  1089.     switch( g_AppState )
  1090.     {
  1091.         case APP_STATE_STARTUP: 
  1092.             *pbNoFurtherProcessing = g_StartUpUI.MsgProc( hWnd, uMsg, wParam, lParam );
  1093.             if( *pbNoFurtherProcessing )
  1094.                 return 0;
  1095.             *pbNoFurtherProcessing = g_StartUpUI2.MsgProc( hWnd, uMsg, wParam, lParam );
  1096.             if( *pbNoFurtherProcessing )
  1097.                 return 0;
  1098.             break;
  1099.  
  1100.         case APP_STATE_SIMULATOR_RUNNING:
  1101.             // Stop the framework from handling F2 & F3
  1102.             if( ( uMsg == WM_KEYDOWN || uMsg == WM_KEYUP ) && (wParam == VK_F3 || wParam == VK_F2) ) 
  1103.             {
  1104.                 *pbNoFurtherProcessing = TRUE;
  1105.                 return 0; 
  1106.             }
  1107.             
  1108.             *pbNoFurtherProcessing = g_SimulatorRunningUI.MsgProc( hWnd, uMsg, wParam, lParam );
  1109.             if( *pbNoFurtherProcessing )
  1110.                 return 0;
  1111.             break;
  1112.  
  1113.         case APP_STATE_RENDER_SCENE: 
  1114.             if( g_bRenderUI || uMsg == WM_KEYDOWN || uMsg == WM_KEYUP )
  1115.             {
  1116.                 *pbNoFurtherProcessing = g_RenderingUI.MsgProc( hWnd, uMsg, wParam, lParam );
  1117.                 if( *pbNoFurtherProcessing )
  1118.                     return 0;
  1119.                 *pbNoFurtherProcessing = g_RenderingUI2.MsgProc( hWnd, uMsg, wParam, lParam );
  1120.                 if( *pbNoFurtherProcessing )
  1121.                     return 0;
  1122.                 *pbNoFurtherProcessing = g_RenderingUI3.MsgProc( hWnd, uMsg, wParam, lParam );
  1123.                 if( *pbNoFurtherProcessing )
  1124.                     return 0;
  1125.                 if( g_bRenderCompressionUI )
  1126.                 {
  1127.                     *pbNoFurtherProcessing = g_CompressionUI.MsgProc( hWnd, uMsg, wParam, lParam );
  1128.                     if( *pbNoFurtherProcessing )
  1129.                         return 0;
  1130.                 }
  1131.             }
  1132.  
  1133.             g_LightControl[g_nActiveLight].HandleMessages( hWnd, uMsg, wParam, lParam );
  1134.  
  1135.             // Pass all remaining windows messages to camera so it can respond to user input
  1136.             g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  1137.             break;
  1138.  
  1139.         default:
  1140.             break;
  1141.     }
  1142.  
  1143.     return 0;
  1144. }
  1145.  
  1146.  
  1147. //--------------------------------------------------------------------------------------
  1148. // Load a mesh and optionally generate the PRT results file if they aren't already cached
  1149. //--------------------------------------------------------------------------------------
  1150. void LoadSceneAndOptGenResults( IDirect3DDevice9* pd3dDevice, WCHAR* strInputMesh, WCHAR* strResultsFile,
  1151.                                 int nNumRays, int nNumBounces, bool bSubSurface )
  1152. {
  1153.     HRESULT hr;
  1154.     WCHAR strResults[MAX_PATH];
  1155.     WCHAR strMesh[MAX_PATH];
  1156.     V( DXUTFindDXSDKMediaFileCch( strMesh, MAX_PATH, strInputMesh ) );
  1157.  
  1158.     hr = DXUTFindDXSDKMediaFileCch( strResults, MAX_PATH, strResultsFile );
  1159.     if( SUCCEEDED(hr) )
  1160.     {
  1161.         LoadScene( pd3dDevice, strInputMesh, strResultsFile );
  1162.     }
  1163.     else
  1164.     {
  1165.         SIMULATOR_OPTIONS options;
  1166.         ZeroMemory( &options, sizeof(SIMULATOR_OPTIONS) );
  1167.  
  1168.         wcscpy( options.strInputMesh, strInputMesh );
  1169.         DXUTGetDXSDKMediaPathCch( options.strInitialDir, MAX_PATH );
  1170.         wcscat( options.strInitialDir, L"" );
  1171.         DXUTFindDXSDKMediaFileCch( options.strInitialDir, MAX_PATH, options.strInputMesh );
  1172.         WCHAR* pLastSlash =  wcsrchr( options.strInitialDir, L'\\' );
  1173.         if( pLastSlash )
  1174.             *pLastSlash = 0;
  1175.         pLastSlash = wcsrchr( strResultsFile, L'\\' );
  1176.         if( pLastSlash )
  1177.             wcscpy( options.strResultsFile, pLastSlash + 1 );
  1178.         else
  1179.             wcscpy( options.strResultsFile, strResultsFile );
  1180.         options.dwOrder = 6;
  1181.         options.dwNumRays = nNumRays;
  1182.         options.dwNumBounces = nNumBounces;
  1183.         options.bSubsurfaceScattering = bSubSurface;
  1184.         options.fLengthScale = 25.0f;
  1185.         options.dwNumChannels = 3;
  1186.  
  1187.         options.dwPredefinedMatIndex = 0;
  1188.         options.fRelativeIndexOfRefraction = 1.3f;
  1189.         options.Diffuse = D3DXCOLOR( 1.00f, 1.00f, 1.00f, 1.0f );
  1190.         options.Absoption = D3DXCOLOR( 0.0030f, 0.0030f, 0.0460f, 1.0f );
  1191.         options.ReducedScattering = D3DXCOLOR( 2.00f, 2.00f, 2.00f, 1.0f );
  1192.  
  1193.         options.bAdaptive = false;
  1194.         options.bRobustMeshRefine = true;
  1195.         options.fRobustMeshRefineMinEdgeLength = 0.0f;
  1196.         options.dwRobustMeshRefineMaxSubdiv = 2;
  1197.         options.bAdaptiveDL = true;
  1198.         options.fAdaptiveDLMinEdgeLength = 0.03f;
  1199.         options.fAdaptiveDLThreshold = 8e-5f;
  1200.         options.dwAdaptiveDLMaxSubdiv = 3;
  1201.         options.bAdaptiveBounce = false;
  1202.         options.fAdaptiveBounceMinEdgeLength = 0.03f;
  1203.         options.fAdaptiveBounceThreshold = 8e-5f;
  1204.         options.dwAdaptiveBounceMaxSubdiv = 3;
  1205.         wcscpy( options.strOutputMesh, L"shapes1_adaptive.x" );
  1206.         options.bBinaryOutputXFile = true;
  1207.  
  1208.         options.bSaveCompressedResults = true;
  1209.         options.Quality = D3DXSHCQUAL_SLOWHIGHQUALITY;
  1210.         options.dwNumPCA = 24;
  1211.         options.dwNumClusters = 1;
  1212.  
  1213.         g_PRTMesh.LoadMesh( pd3dDevice, strInputMesh );
  1214.  
  1215.         // Update camera's viewing radius based on the object radius
  1216.         float fObjectRadius = g_PRTMesh.GetObjectRadius();
  1217.         if( g_fCurObjectRadius != fObjectRadius )
  1218.         {
  1219.             g_fCurObjectRadius = fObjectRadius;
  1220.             g_Camera.SetRadius( fObjectRadius*3.0f, fObjectRadius*0.1f, fObjectRadius*20.0f );
  1221.         }
  1222.         g_Camera.SetModelCenter( g_PRTMesh.GetObjectCenter() );
  1223.         for( int i=0; i<MAX_LIGHTS; i++ )
  1224.             g_LightControl[i].SetRadius(fObjectRadius);
  1225.  
  1226.         g_Simulator.Run( pd3dDevice, &options, &g_PRTMesh );
  1227.         g_AppState = APP_STATE_SIMULATOR_RUNNING;
  1228.         DXUTSetMultimonSettings( false );
  1229.     }
  1230. }
  1231.  
  1232.  
  1233. //--------------------------------------------------------------------------------------
  1234. void LoadScene( IDirect3DDevice9* pd3dDevice, WCHAR* strInputMesh, WCHAR* strResultsFile )
  1235. {
  1236.     HRESULT hr;
  1237.     WCHAR strResults[MAX_PATH];
  1238.     WCHAR strMesh[MAX_PATH];
  1239.     V( DXUTFindDXSDKMediaFileCch( strMesh, MAX_PATH, strInputMesh ) );
  1240.     V( DXUTFindDXSDKMediaFileCch( strResults, MAX_PATH, strResultsFile ) );
  1241.  
  1242.     g_PRTMesh.LoadMesh( pd3dDevice, strMesh );
  1243.  
  1244.     // Setup the camera's view parameters
  1245.     D3DXVECTOR3 vecEye(0.0f, 0.0f, -5.0f);
  1246.     D3DXVECTOR3 vecAt (0.0f, 0.0f, -0.0f);
  1247.     g_Camera.Reset();
  1248.     g_Camera.SetViewQuat( D3DXQUATERNION(0,0,0,1) );
  1249.     g_Camera.SetWorldQuat( D3DXQUATERNION(0,0,0,1) );
  1250.     g_Camera.SetViewParams( &vecEye, &vecAt );
  1251.  
  1252.     // Update camera's viewing radius based on the object radius
  1253.     float fObjectRadius = g_PRTMesh.GetObjectRadius();
  1254.     g_fCurObjectRadius = fObjectRadius;
  1255.     g_Camera.SetRadius( fObjectRadius*3.0f, fObjectRadius*0.1f, fObjectRadius*20.0f );
  1256.     g_Camera.SetModelCenter( g_PRTMesh.GetObjectCenter() );
  1257.  
  1258.     for( int i=0; i<MAX_LIGHTS; i++ )
  1259.         g_LightControl[i].SetRadius(fObjectRadius);
  1260.  
  1261.     WCHAR* pLastDot =  wcsrchr( strResults, L'.' );
  1262.     bool bLoadCompressed = false;
  1263.     if( pLastDot )
  1264.     {
  1265.         if( wcscmp(pLastDot, L".prt") == 0 )
  1266.             bLoadCompressed = false;
  1267.         if( wcscmp(pLastDot, L".pca") == 0 )
  1268.             bLoadCompressed = true;
  1269.     }
  1270.  
  1271.     if( bLoadCompressed )
  1272.     {
  1273.         g_PRTMesh.LoadCompPRTBufferFromFile( strResults );
  1274.     }
  1275.     else
  1276.     {
  1277.         g_PRTMesh.LoadPRTBufferFromFile( strResults );
  1278.         g_PRTMesh.CompressBuffer( D3DXSHCQUAL_FASTLOWQUALITY, 1, 24 );
  1279.     }
  1280.  
  1281.     g_PRTMesh.ExtractCompressedDataForPRTShader();
  1282.     g_PRTMesh.LoadEffects( pd3dDevice, DXUTGetDeviceCaps() );
  1283.  
  1284.     g_AppState = APP_STATE_RENDER_SCENE;                
  1285.     g_bRenderCompressionUI = false;
  1286. }
  1287.  
  1288. //--------------------------------------------------------------------------------------
  1289. void ResetUI()
  1290. {
  1291.     g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->SetRange( 0, 200 );
  1292.  
  1293.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_A)->SetSelectedByData( IntToPtr(0) );
  1294.     g_RenderingUI.GetComboBox(IDC_ENVIRONMENT_B)->SetSelectedByData( IntToPtr(2) );
  1295.     g_RenderingUI.GetSlider(IDC_ENVIRONMENT_1_SCALER)->SetValue( 50 ); 
  1296.     g_RenderingUI.GetSlider(IDC_ENVIRONMENT_2_SCALER)->SetValue( 50 ); 
  1297.     g_RenderingUI.GetSlider(IDC_ENVIRONMENT_BLEND_SCALER)->SetValue( 0 ); 
  1298.  
  1299.     g_RenderingUI2.GetCheckBox( IDC_RENDER_UI )->SetChecked( true );
  1300.     g_RenderingUI2.GetCheckBox( IDC_RENDER_MAP )->SetChecked( true );
  1301.     g_bRenderEnvMap = true;
  1302.     g_RenderingUI2.GetCheckBox( IDC_RENDER_ARROWS )->SetChecked( true );
  1303.     g_RenderingUI2.GetCheckBox( IDC_RENDER_MESH )->SetChecked( true );
  1304.     g_RenderingUI2.GetCheckBox( IDC_RENDER_TEXTURE )->SetChecked( true );
  1305.     g_RenderingUI2.GetCheckBox( IDC_WIREFRAME )->SetChecked( false );
  1306.     g_RenderingUI2.GetCheckBox( IDC_SH_PROJECTION )->SetChecked( false );
  1307.  
  1308.     g_RenderingUI3.GetRadioButton( IDC_TECHNIQUE_NDOTL )->SetChecked( true, true );
  1309.     g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->SetValue( 100 );
  1310.     g_RenderingUI3.GetRadioButton( IDC_TECHNIQUE_SHIRRAD )->SetChecked( true, true );
  1311.     g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->SetValue( 0 );
  1312.     g_RenderingUI3.GetRadioButton( IDC_TECHNIQUE_PRT )->SetChecked( true, true );
  1313.     g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->SetValue( 0 );
  1314.     g_RenderingUI2.GetSlider( IDC_NUM_LIGHTS )->SetValue( 1 );
  1315.  
  1316.     WCHAR sz[100];
  1317.     _snwprintf( sz, 100, L"# Lights: %d", g_RenderingUI2.GetSlider( IDC_NUM_LIGHTS )->GetValue() ); sz[99] = 0;
  1318.     g_RenderingUI2.GetStatic( IDC_NUM_LIGHTS_STATIC )->SetText( sz );
  1319.     g_nNumActiveLights = g_RenderingUI2.GetSlider( IDC_NUM_LIGHTS )->GetValue();
  1320.     g_nActiveLight %= g_nNumActiveLights;
  1321.  
  1322.     g_RenderingUI2.GetSlider( IDC_LIGHT_ANGLE )->SetValue( 45 );
  1323.     int nLightAngle = g_RenderingUI2.GetSlider( IDC_LIGHT_ANGLE )->GetValue();
  1324.     _snwprintf( sz, 100, L"Cone Angle: %d", nLightAngle ); sz[99] = 0;
  1325.     g_RenderingUI2.GetStatic( IDC_LIGHT_ANGLE_STATIC )->SetText( sz );
  1326.  
  1327.     g_RenderingUI3.GetRadioButton( IDC_TECHNIQUE_PRT )->SetChecked( true, true );
  1328. }
  1329.  
  1330.  
  1331.  
  1332. //--------------------------------------------------------------------------------------
  1333. // As a convenience, the sample framework inspects the incoming windows messages for
  1334. // keystroke messages and decodes the message parameters to pass relevant keyboard
  1335. // messages to the application.  The framework does not remove the underlying keystroke 
  1336. // messages, which are still passed to the application's MsgProc callback.
  1337. //--------------------------------------------------------------------------------------
  1338. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  1339. {
  1340.     if( bKeyDown )
  1341.     {
  1342.         switch( nChar )
  1343.         {
  1344.             // Demo hotkeys
  1345.             case 'Z': 
  1346.             {
  1347.                 LoadSceneAndOptGenResults( DXUTGetD3DDevice(), L"PRT Demo\\cube_on_plane.x", 
  1348.                         L"PRT Demo\\cube_on_plane_1k_6b_prtresults.pca", 1024, 6, false ); 
  1349.  
  1350.                 g_RenderingUI.EnableNonUserEvents( true );
  1351.                 g_RenderingUI2.EnableNonUserEvents( true );
  1352.                 g_RenderingUI3.EnableNonUserEvents( true );
  1353.                 ResetUI();
  1354.                 g_RenderingUI2.GetCheckBox( IDC_RENDER_TEXTURE )->SetChecked( false );
  1355.                 g_RenderingUI.EnableNonUserEvents( false );
  1356.                 g_RenderingUI2.EnableNonUserEvents( false );
  1357.                 g_RenderingUI3.EnableNonUserEvents( false );
  1358.                 break;
  1359.             }
  1360.  
  1361.             case 'X': 
  1362.             {
  1363.                 LoadSceneAndOptGenResults( DXUTGetD3DDevice(), L"PRT Demo\\LandShark.x", 
  1364.                         L"PRT Demo\\02_LandShark_1k_prtresults.pca", 1024, 1, false ); 
  1365.  
  1366.                 g_RenderingUI.EnableNonUserEvents( true );
  1367.                 g_RenderingUI2.EnableNonUserEvents( true );
  1368.                 g_RenderingUI3.EnableNonUserEvents( true );
  1369.                 ResetUI();
  1370.                 g_RenderingUI.EnableNonUserEvents( false );
  1371.                 g_RenderingUI2.EnableNonUserEvents( false );
  1372.                 g_RenderingUI3.EnableNonUserEvents( false );
  1373.                 break;
  1374.             }
  1375.  
  1376.             case 'C': 
  1377.             {
  1378.                 LoadSceneAndOptGenResults( DXUTGetD3DDevice(), L"PRT Demo\\wall_with_pillars.x", 
  1379.                     L"PRT Demo\\wall_with_pillars_1k_prtresults.pca", 1024, 1, false ); 
  1380.  
  1381.                 g_RenderingUI.EnableNonUserEvents( true );
  1382.                 g_RenderingUI2.EnableNonUserEvents( true );
  1383.                 g_RenderingUI3.EnableNonUserEvents( true );
  1384.                 ResetUI();
  1385.                 g_RenderingUI.EnableNonUserEvents( false );
  1386.                 g_RenderingUI2.EnableNonUserEvents( false );
  1387.                 g_RenderingUI3.EnableNonUserEvents( false );
  1388.                 break;
  1389.             }
  1390.  
  1391.             case 'V': 
  1392.             {
  1393.                 LoadSceneAndOptGenResults( DXUTGetD3DDevice(), L"PRT Demo\\Head_Sad.x", 
  1394.                     L"PRT Demo\\Head_Sad_1k_prtresults.pca", 1024, 1, false ); 
  1395.  
  1396.                 g_RenderingUI.EnableNonUserEvents( true );
  1397.                 g_RenderingUI2.EnableNonUserEvents( true );
  1398.                 g_RenderingUI3.EnableNonUserEvents( true );
  1399.                 ResetUI();
  1400.                 g_RenderingUI.EnableNonUserEvents( false );
  1401.                 g_RenderingUI2.EnableNonUserEvents( false );
  1402.                 g_RenderingUI3.EnableNonUserEvents( false );
  1403.                 break;
  1404.             }
  1405.  
  1406.             case 'B': 
  1407.             {
  1408.                 LoadSceneAndOptGenResults( DXUTGetD3DDevice(), L"PRT Demo\\Head_Big_Ears.x", 
  1409.                     L"PRT Demo\\Head_Big_Ears_1k_subsurf_prtresults.pca", 1024, 1, true ); 
  1410.  
  1411.                 g_RenderingUI.EnableNonUserEvents( true );
  1412.                 g_RenderingUI2.EnableNonUserEvents( true );
  1413.                 g_RenderingUI3.EnableNonUserEvents( true );
  1414.                 ResetUI();
  1415.                 g_RenderingUI.GetSlider(IDC_ENVIRONMENT_1_SCALER)->SetValue( 0 ); 
  1416.                 g_RenderingUI.GetSlider(IDC_ENVIRONMENT_2_SCALER)->SetValue( 0 ); 
  1417.                 g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->SetRange( 0, 1000 );
  1418.                 g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->SetValue( 200 );
  1419.                 g_RenderingUI.EnableNonUserEvents( false );
  1420.                 g_RenderingUI2.EnableNonUserEvents( false );
  1421.                 g_RenderingUI3.EnableNonUserEvents( false );
  1422.                 break;
  1423.             }
  1424.  
  1425.             case VK_F1: g_bShowHelp = !g_bShowHelp; break;
  1426.             case VK_F8:
  1427.             case 'W': g_bWireframe = !g_bWireframe; g_RenderingUI2.GetCheckBox( IDC_WIREFRAME )->SetChecked(g_bWireframe); break;
  1428.         }
  1429.     }
  1430. }
  1431.  
  1432.  
  1433. //--------------------------------------------------------------------------------------
  1434. // Handles the GUI events
  1435. //--------------------------------------------------------------------------------------
  1436. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  1437. {
  1438.     switch( nControlID )
  1439.     {
  1440.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  1441.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  1442.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  1443.  
  1444.         case IDC_SCENE_1: KeyboardProc( 'Z', true, false ); break;
  1445.         case IDC_SCENE_2: KeyboardProc( 'X', true, false ); break;
  1446.         case IDC_SCENE_3: KeyboardProc( 'C', true, false ); break;
  1447.         case IDC_SCENE_4: KeyboardProc( 'V', true, false ); break;
  1448.         case IDC_SCENE_5: KeyboardProc( 'B', true, false ); break;
  1449.  
  1450.         case IDC_ACTIVE_LIGHT:
  1451.             if( !g_LightControl[g_nActiveLight].IsBeingDragged() )
  1452.             {
  1453.                 g_nActiveLight++;
  1454.                 g_nActiveLight %= g_nNumActiveLights;
  1455.             }
  1456.             break;
  1457.  
  1458.         case IDC_NUM_LIGHTS:
  1459.             if( !g_LightControl[g_nActiveLight].IsBeingDragged() )
  1460.             {
  1461.                 WCHAR sz[100];
  1462.                 _snwprintf( sz, 100, L"# Lights: %d", g_RenderingUI2.GetSlider( IDC_NUM_LIGHTS )->GetValue() ); sz[99] = 0;
  1463.                 g_RenderingUI2.GetStatic( IDC_NUM_LIGHTS_STATIC )->SetText( sz );
  1464.  
  1465.                 g_nNumActiveLights = g_RenderingUI2.GetSlider( IDC_NUM_LIGHTS )->GetValue();
  1466.                 g_nActiveLight %= g_nNumActiveLights;
  1467.             }
  1468.             break;
  1469.  
  1470.         case IDC_LIGHT_SCALE: 
  1471.         {
  1472.             WCHAR sz[100];
  1473.             float fLightScale = (float) (g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->GetValue() * 0.01f);
  1474.             _snwprintf( sz, 100, L"Light scale: %0.2f", fLightScale ); sz[99] = 0;
  1475.             g_RenderingUI2.GetStatic( IDC_LIGHT_SCALE_STATIC )->SetText( sz );
  1476.  
  1477.             bool bEnable = (g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->GetValue() != 0 );
  1478.             g_RenderingUI2.GetSlider( IDC_LIGHT_ANGLE )->SetEnabled( bEnable );
  1479.             g_RenderingUI2.GetSlider( IDC_NUM_LIGHTS )->SetEnabled( bEnable );
  1480.             g_RenderingUI2.GetStatic( IDC_LIGHT_ANGLE_STATIC )->SetEnabled( bEnable );
  1481.             g_RenderingUI2.GetStatic( IDC_NUM_LIGHTS_STATIC )->SetEnabled( bEnable );
  1482.             g_RenderingUI2.GetButton( IDC_ACTIVE_LIGHT )->SetEnabled( bEnable );
  1483.             break;
  1484.         }
  1485.  
  1486.         case IDC_LIGHT_ANGLE:
  1487.         {
  1488.             WCHAR sz[100];
  1489.             int nLightAngle = g_RenderingUI2.GetSlider( IDC_LIGHT_ANGLE )->GetValue();
  1490.             _snwprintf( sz, 100, L"Cone Angle: %d", nLightAngle ); sz[99] = 0;
  1491.             g_RenderingUI2.GetStatic( IDC_LIGHT_ANGLE_STATIC )->SetText( sz );
  1492.             break;
  1493.         }
  1494.  
  1495.         case IDC_SIMULATOR:
  1496.             g_AppState = APP_STATE_SIMULATOR_OPTIONS;
  1497.             break;
  1498.  
  1499.         case IDC_LOAD_PRTBUFFER:
  1500.             g_AppState = APP_STATE_LOAD_PRT_BUFFER;
  1501.             break;
  1502.  
  1503.         case IDC_STOP_SIMULATOR:
  1504.             g_Simulator.Stop();
  1505.             g_AppState = APP_STATE_STARTUP;
  1506.             break;
  1507.  
  1508.         case IDC_ENVIRONMENT_A:
  1509.             g_dwSkyBoxA = PtrToInt( g_RenderingUI.GetComboBox( IDC_ENVIRONMENT_A )->GetSelectedData() );
  1510.             break;
  1511.  
  1512.         case IDC_ENVIRONMENT_B:
  1513.             g_dwSkyBoxB = PtrToInt( g_RenderingUI.GetComboBox( IDC_ENVIRONMENT_B )->GetSelectedData() );
  1514.             break;
  1515.  
  1516.         case IDC_TECHNIQUE_PRT:     
  1517.         {
  1518.             float fLightScale = (float) (g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->GetValue() * 0.01f);
  1519.             switch( g_dwTechnique ) 
  1520.             { 
  1521.                 case 0: g_fLightScaleForPRT = fLightScale; break; 
  1522.                 case 1: g_fLightScaleForSHIrrad = fLightScale; break; 
  1523.                 case 2: g_fLightScaleForNdotL = fLightScale; break; 
  1524.             }
  1525.             g_dwTechnique = 0; 
  1526.  
  1527.             g_RenderingUI2.GetCheckBox( IDC_RENDER_MAP )->SetChecked( true );
  1528.             g_bRenderEnvMap = true;
  1529.  
  1530.             g_RenderingUI2.EnableNonUserEvents( true );
  1531.             g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->SetValue( (int)(g_fLightScaleForPRT*100.0f) ); 
  1532.             g_RenderingUI2.EnableNonUserEvents( false );
  1533.             break;
  1534.         }
  1535.  
  1536.         case IDC_TECHNIQUE_SHIRRAD: 
  1537.         {
  1538.             float fLightScale = (float) (g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->GetValue() * 0.01f);
  1539.             switch( g_dwTechnique ) 
  1540.             { 
  1541.                 case 0: g_fLightScaleForPRT = fLightScale; break; 
  1542.                 case 1: g_fLightScaleForSHIrrad = fLightScale; break; 
  1543.                 case 2: g_fLightScaleForNdotL = fLightScale; break; 
  1544.             }
  1545.             g_dwTechnique = 1; 
  1546.             g_RenderingUI2.GetCheckBox( IDC_RENDER_MAP )->SetChecked( true );
  1547.             g_bRenderEnvMap = true;
  1548.             g_RenderingUI2.EnableNonUserEvents( true );
  1549.             g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->SetValue( (int)(g_fLightScaleForSHIrrad*100.0f) ); 
  1550.             g_RenderingUI2.EnableNonUserEvents( false );
  1551.             break;
  1552.         }
  1553.  
  1554.         case IDC_TECHNIQUE_NDOTL:   
  1555.         {
  1556.             float fLightScale = (float) (g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->GetValue() * 0.01f);
  1557.             switch( g_dwTechnique ) 
  1558.             { 
  1559.                 case 0: g_fLightScaleForPRT = fLightScale; break; 
  1560.                 case 1: g_fLightScaleForSHIrrad = fLightScale; break; 
  1561.                 case 2: g_fLightScaleForNdotL = fLightScale; break; 
  1562.             }
  1563.             g_dwTechnique = 2; 
  1564.             g_RenderingUI2.GetCheckBox( IDC_RENDER_MAP )->SetChecked( false );
  1565.             g_bRenderEnvMap = false;
  1566.             g_RenderingUI2.EnableNonUserEvents( true );
  1567.             g_RenderingUI2.GetSlider( IDC_LIGHT_SCALE )->SetValue( (int)(g_fLightScaleForNdotL*100.0f) ); 
  1568.             g_RenderingUI2.EnableNonUserEvents( false );
  1569.             break;
  1570.         }
  1571.  
  1572.         case IDC_COMPRESSION:
  1573.             if( g_PRTMesh.IsUncompressedBufferLoaded() )
  1574.             {
  1575.                 g_bRenderCompressionUI = !g_bRenderCompressionUI;
  1576.             }
  1577.             else
  1578.             {
  1579.                 MessageBox( DXUTGetHWND(), L"To change compression settings during rendering, please load an uncompressed buffer.  To make one use the simulator settings dialog to save an uncompressed buffer.", L"PRTPerVertex", MB_OK );
  1580.             }
  1581.             break;
  1582.  
  1583.         case IDC_RESTART:
  1584.             g_AppState = APP_STATE_STARTUP;
  1585.             break;
  1586.  
  1587.         case IDC_RENDER_UI: g_bRenderUI = g_RenderingUI2.GetCheckBox( IDC_RENDER_UI )->GetChecked(); break;
  1588.         case IDC_RENDER_MAP: g_bRenderEnvMap = g_RenderingUI2.GetCheckBox( IDC_RENDER_MAP )->GetChecked(); break;
  1589.         case IDC_RENDER_ARROWS: g_bRenderArrows = g_RenderingUI2.GetCheckBox( IDC_RENDER_ARROWS )->GetChecked(); break;
  1590.         case IDC_RENDER_MESH: g_bRenderMesh = g_RenderingUI2.GetCheckBox( IDC_RENDER_MESH )->GetChecked(); break;
  1591.         case IDC_WIREFRAME: g_bWireframe = g_RenderingUI2.GetCheckBox( IDC_WIREFRAME )->GetChecked(); break;
  1592.         case IDC_RENDER_TEXTURE: g_bRenderWithAlbedoTexture = g_RenderingUI2.GetCheckBox( IDC_RENDER_TEXTURE )->GetChecked(); break;
  1593.         case IDC_SH_PROJECTION: g_bRenderSHProjection = g_RenderingUI2.GetCheckBox( IDC_SH_PROJECTION )->GetChecked(); break;
  1594.  
  1595.         case IDC_NUM_PCA:
  1596.         {
  1597.             WCHAR sz[256];
  1598.             DWORD dwNumPCA = g_CompressionUI.GetSlider( IDC_NUM_PCA )->GetValue() * 4;
  1599.             swprintf( sz, L"Number of PCA: %d", dwNumPCA );
  1600.             g_CompressionUI.GetStatic( IDC_NUM_PCA_TEXT )->SetText( sz );           
  1601.  
  1602.             UpdateConstText();
  1603.             break;
  1604.         }
  1605.  
  1606.         case IDC_NUM_CLUSTERS:
  1607.         {
  1608.             WCHAR sz[256];
  1609.             DWORD dwNumClusters = g_CompressionUI.GetSlider( IDC_NUM_CLUSTERS )->GetValue();
  1610.             swprintf( sz, L"Number of Clusters: %d", dwNumClusters );
  1611.             g_CompressionUI.GetStatic( IDC_NUM_CLUSTERS_TEXT )->SetText( sz );           
  1612.  
  1613.             UpdateConstText();
  1614.             break;
  1615.         }
  1616.  
  1617.         case IDC_APPLY:
  1618.         {
  1619.             DWORD dwNumPCA = g_CompressionUI.GetSlider( IDC_NUM_PCA )->GetValue() * 4;
  1620.             DWORD dwNumClusters = g_CompressionUI.GetSlider( IDC_NUM_CLUSTERS )->GetValue();
  1621.  
  1622.             SIMULATOR_OPTIONS& options = GetGlobalOptions();
  1623.             options.dwNumClusters = dwNumClusters;
  1624.             options.dwNumPCA = dwNumPCA;
  1625.             GetGlobalOptionsFile().SaveOptions();
  1626.  
  1627.             g_PRTMesh.CompressBuffer( options.Quality, options.dwNumClusters, options.dwNumPCA );
  1628.             g_PRTMesh.ExtractCompressedDataForPRTShader();
  1629.             g_PRTMesh.LoadEffects( DXUTGetD3DDevice(), DXUTGetDeviceCaps() );
  1630.             break;
  1631.         }
  1632.     }
  1633. }
  1634.  
  1635.  
  1636. //--------------------------------------------------------------------------------------
  1637. // This callback function will be called immediately after the Direct3D device has 
  1638. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  1639. // in the OnResetDevice callback should be released here, which generally includes all 
  1640. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  1641. // information about lost devices.
  1642. //--------------------------------------------------------------------------------------
  1643. void CALLBACK OnLostDevice()
  1644. {
  1645.     for(int i=0; i<NUM_SKY_BOXES; ++i )
  1646.         g_Skybox[i].OnLostDevice();
  1647.     CDXUTDirectionWidget::StaticOnLostDevice();
  1648.     if( g_pFont )
  1649.         g_pFont->OnLostDevice();
  1650.     SAFE_RELEASE( g_pTextSprite );
  1651.     g_PRTMesh.OnLostDevice();
  1652. }
  1653.  
  1654.  
  1655. //--------------------------------------------------------------------------------------
  1656. // This callback function will be called immediately after the Direct3D device has 
  1657. // been destroyed, which generally happens as a result of application termination or 
  1658. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  1659. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  1660. //--------------------------------------------------------------------------------------
  1661. void CALLBACK OnDestroyDevice()
  1662. {
  1663.     for(int i=0; i<NUM_SKY_BOXES; ++i )
  1664.         g_Skybox[i].OnDestroyDevice();
  1665.     g_PRTMesh.OnDestroyDevice();
  1666.     CDXUTDirectionWidget::StaticOnDestroyDevice();
  1667.     SAFE_RELEASE( g_pFont );
  1668.     g_Simulator.Stop();
  1669. }
  1670.  
  1671.  
  1672.  
  1673. //-----------------------------------------------------------------------------
  1674. // update the dlg's text & controls
  1675. //-----------------------------------------------------------------------------
  1676. void UpdateConstText()
  1677. {
  1678.     WCHAR sz[256];
  1679.     DWORD dwNumClusters = g_CompressionUI.GetSlider( IDC_NUM_CLUSTERS )->GetValue();
  1680.     DWORD dwNumPCA = g_CompressionUI.GetSlider( IDC_NUM_PCA )->GetValue() * 4;
  1681.     DWORD dwMaxVertexShaderConst = DXUTGetDeviceCaps()->MaxVertexShaderConst;
  1682.     DWORD dwNumVConsts = dwNumClusters * (1 + 3*dwNumPCA/4) + 4;
  1683.     swprintf( sz, L"%d * (1 + (3*%d/4)) + 4 = %d", dwNumClusters, dwNumPCA, dwNumVConsts );
  1684.     g_CompressionUI.GetStatic( IDC_CUR_CONSTANTS )->SetText( sz );
  1685.  
  1686.     bool bEnable = ( dwNumVConsts < dwMaxVertexShaderConst );
  1687.     g_CompressionUI.GetButton( IDC_APPLY )->SetEnabled( bEnable );
  1688. }
  1689.  
  1690.  
  1691.